from django.shortcuts import render
from django.views import View
import json,pickle,base64
from django import http
from django_redis import get_redis_connection

import logging
logger = logging.getLogger('django')

from goods.models import SKU
from meiduo_mail.utils.response_code import RETCODE

# Create your views here.


class CartsView(View):
    """购物车"""
    def post(self,request):

        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get('sku_id')
        count = json_dict.get('count')
        selected = json_dict.get('selected',True)
        if all([sku_id, count]) is False:
            return http.HttpResponseForbidden('缺少必传参数')
        try:
            sku = SKU.objects.get(id=sku_id,is_launched=True)
        except:
            return http.HttpResponseForbidden('sku_id错误')

        try:
            count = int(count)
        except Exception as e:
            logger.error(e)
            return http.HttpResponseForbidden('参数类型有误')
        if isinstance(selected,bool) is False:
            return http.HttpResponseForbidden('参数类型有误')
        user = request.user
        if user.is_authenticated:
            # 以登陆用户redis
            redis_conn = get_redis_connection('carts')
            pl = redis_conn.pipeline()
            pl.hincrby('cart_%s' % user.id, sku_id, count)
            if selected:
                pl.sadd('selected_%s' % user.id,sku_id)
            pl.execute()
            return http.JsonResponse({'code':RETCODE.OK,'errmsg':'添加购物车成功'})

        else:
            # 未登录用户cookie
            # 尝试取出cookie中的购物车数据
            cart_str = request.COOKIES.get('carts')
            # 判断用户是否已经有了cookie购物车数据
            if cart_str:
                cart_dict = pickle.loads(base64.b64decode(cart_str.encode()))
                if sku_id in cart_dict:
                    origin_count = cart_dict[sku_id]['count']
                    count += origin_count
            else:
                cart_dict = {}
                # 向cookie大字典中添加新的购物车商品数据
            cart_dict[sku_id] = {'count': count, 'selected': selected}
            # 将cookie大字典再转换回字符串
            bytes_un = pickle.dumps(cart_dict)
            bytes_str = base64.b64encode(bytes_un)
            cart_str = bytes_str.decode()

            response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': '添加购物车成功'})
            response.set_cookie('carts', cart_str)

            return response

    def get(self,request):
        # 判断用户是否登陆
        #     登陆用户
        """
                    {
                        sku_id_1: {'count': 1, 'selected': True},
                        sku_id_12: {'count': 1, 'selected': False}

                    }
                """
        #     创建redis连接
        #     获取redis中的购物车数据
        #     将redis购物车数据转换成cookie购物车大字典格式

        #     未登录用户
        #     获取cookie购物车数据
        #     判断是否有购物车数据
        #     如果有将cookie购物车数据转换成字典
        #     没有则渲染空白的页面
        # 查询sku模型
        # 包装模板渲染数据


        user = request.user
        if user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            redis_carts = redis_conn.hgetall('cart_%s' % user.id)
            selected_ids = redis_conn.smembers('selected_%s' % user.id)

            cart_dict = {}
            for sku_id_bytes in redis_carts:
                cart_dict[int(sku_id_bytes)] = {
                    'count' :int(redis_carts[sku_id_bytes]),
                    'selected':sku_id_bytes in selected_ids
                }
        else:
            cart_str = request.COOKIES.get('carts')
            if cart_str:
                cart_dict = pickle.loads(base64.b64decode(cart_str.encode()))
            else:
                return render(request,'cart.html')

        #     未登录用户
        #     获取cookie购物车数据
        #     判断是否有购物车数据
        #     如果有将cookie购物车数据转换成字典
        #     没有则渲染空白的页面
        # 查询sku模型
        # 包装模板渲染数据
        sku_qs = SKU.objects.filter(id__in=cart_dict.keys())
        sku_list = []
        for sku_model in sku_qs:
            count = cart_dict[sku_model.id]['count']
            sku_list.append({
                'id':sku_model.id,
                'name':sku_model.name,
                'default_image_url':sku_model.default_image.url,
                'price':str(sku_model.price),
                'count':count,
                'selected':str(cart_dict[sku_model.id]['selected']),
                'amount':str(sku_model.price * count)
            })
        return render(request,'cart.html',{'cart_skus':sku_list})

        # 判断用户是否登录
        # user = request.user
        # if user.is_authenticated:
        #     # 如果是登录用户获取redis中购物车数据
        #     # 创建redis连接对象
        #     redis_conn = get_redis_connection('carts')
        #     # 获取hash数据  {sku_id_1: count, sku_id_2: count}
        #     redis_carts = redis_conn.hgetall('cart_%s' % user.id)
        #     # 获取set数据 {sku_id_1}
        #     selected_ids = redis_conn.smembers('selected_%s' % user.id)
        #     """
        #         {
        #             sku_id_1: {'count': 1, 'selected': True},
        #             sku_id_12: {'count': 1, 'selected': False}
        #
        #         }
        #     """
        #     # 将redis购物车数据转换成cookie购物车大字典格式
        #     cart_dict = {}  # 用来包装redis购物车的所有数据
        #     for sku_id_bytes in redis_carts:
        #         cart_dict[int(sku_id_bytes)] = {
        #             'count': int(redis_carts[sku_id_bytes]),
        #             'selected': sku_id_bytes in selected_ids
        #         }
        #
        # else:
        #     # 如果是未登录用户获取cookie中购物车数据
        #     # 获取cookie购物车数据
        #     cart_str = request.COOKIES.get('carts')
        #     # 判断是否有cookie购物车数据
        #     if cart_str:
        #         # 如果获取到cookie购物车数据将str车换成字典
        #         cart_dict = pickle.loads(base64.b64decode(cart_str.encode()))
        #     else:
        #         # 如果没有获取到cookie购物车数据,直接渲染空白的购物车界面
        #         return render(request, 'cart.html')
        #
        # # 查询sku模型
        # sku_qs = SKU.objects.filter(id__in=cart_dict.keys())
        # sku_list = []  # 用来包装模板渲染时的所有sku字典数据
        # # 包装模板渲染时的数据
        # for sku_model in sku_qs:
        #     count = cart_dict[sku_model.id]['count']
        #     sku_list.append(
        #         {
        #             'id': sku_model.id,
        #             'name': sku_model.name,
        #             'default_image_url': sku_model.default_image.url,
        #             'price': str(sku_model.price),
        #             'count': count,
        #             'selected': str(cart_dict[sku_model.id]['selected']),
        #             'amount': str(sku_model.price * count)
        #         }
        #     )
        #
        # return render(request, 'cart.html', {'cart_skus': sku_list})

    def put(self,request):
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict['sku_id']
        count = json_dict['count']
        selected = json_dict['selected']

        if all([sku_id,count]) is False:
            return http.HttpResponseForbidden('缺少必传参数')
        try:
            sku = SKU.objects.get(id=sku_id,is_launched=True)
        except SKU.DoesNotExist:
            return http.HttpResponseForbidden('sku_id错误')

        try:
            coutn = int(count)
        except Exception as e:
            logger.error(e)
            return http.HttpResponseForbidden('参数类型有误')
        if isinstance(selected,bool) is False:
            return http.HttpResponseForbidden('参数类型有误')

        sku_dict = {
            'id': sku_id,
            'naem': sku.name,
            'default_image_url': sku.default_image.url,
            'price': str(sku.price),
            'count': count,
            'selected': selected,
            'amout': sku.price * count
        }
        response = http.JsonResponse({'code':RETCODE.OK,'errmsg':'修改购物车数据成功','cart_sku': sku_dict})

        user = request.user
        # 以登陆,修改redis数据
        # 未登录，修改cookie数据

        if user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            redis_conn.hset('cart_%s' % user.id, sku_id, count)
            if selected:
                redis_conn.sadd('selected_%s' % user.id, sku_id)
            else:
                redis_conn.srem('selected_%s' % user.id, sku_id)
        else:
            # 未登录用户修改cookie数据
            # 将cart——str转成bytes再转乘base64bytes在转字典
            cart_str = request.COOKIES.get('carts')
            if cart_str:
                cart_dict = pickle.loads(base64.b64decode(cart_str.encode()))
            else:
                return http.HttpResponseForbidden('没有cookie')
            cart_dict[sku_id] = {
                'count': count,
                'selected': selected
            }

            cart_str = base64.b64encode(pickle.dumps(cart_dict)).decode()
            response.set_cookie('carts', cart_str)

        return response

    def delete(self,request):
        # 接受
        # 校验
        # 判断用户是否登陆
        # 登陆用户删除redis数据
        #     创建连接对象
        #     删除hash
        #     删除set
        # 未登录用户删除cokie数据
        #     获取cookie购物车数据
        #     若获取到，字符串转字典
        #     为获取到，提前响应
        #     删除指定skuid的兼职对
        #     判断当前字带年是否为空
        #         为空删除cookie，进行响应
        #     不为空则字典转字符串
        #     设置cookie'' \
        #     响应

        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get('sku_id')

        try:
            sku = SKU.objects.get(id=sku_id,is_launched=True)
        except SKU.DoesNotExist:
            return http.HttpResponseForbidden('sku_id错误')

        user = request.user
        if user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            redis_conn.hdel('cart_%s' % user.id, sku_id)
            redis_conn.srem('selected_%s' % user.id, sku_id)
            return http.JsonResponse({'code':RETCODE.OK,'errmsg':'删除成功'})


        else:
                # 未登录用户删除cokie数据
                #     获取cookie购物车数据
                #     若获取到，字符串转字典
                #     为获取到，提前响应
                #     删除指定skuid的兼职对
                #     判断当前字带年是否为空
                #         为空删除cookie，进行响应
                #     不为空则字典转字符串
                #     设置cookie'' \
                #     响应
            cart_str = request.COOKIES.get('carts')
            if cart_str:
                cart_dict = pickle.loads(base64.b64decode(cart_str.encode()))
            else:
                return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': 'cookie数据没获取到'})

            if sku_id in cart_dict:
                del cart_dict[sku_id]

            response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': "删除购物车成功"})
            if not cart_dict:
                response.delete_cookie('carts')
                return response

            cart_str = base64.b64encode(pickle.dumps(cart_dict)).decode()
            response.set_cookie('carts', cart_str)
            return response

class CartsSelectedAllView(View):
    def put(self,request):
        # 接受
        # 校验
        # 判断用户是否登陆
        # 登陆用户从哦呵做redis
        # 未登录用户操作cookies
        json_dict = json.loads(request.body.decode())
        selected = json_dict.get('selected')

        if isinstance(selected, bool) is False:
            return http.HttpResponseForbidden('参数selected有误')

        user = request.user
        if user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            if selected:
                redis_carts = redis_conn.hgetall('cart_%s' % user.id)
                redis_conn.sadd('selected_%s' % user.id, *redis_carts.keys())
            else:
                redis_conn.delete('selected_%s' % user.id)
            return http.JsonResponse({'code':RETCODE.OK,'errmsg':'OK'})
        else:

            # 获取购物车cookie数据
            # 判断是否取得cookie购物车数据
            #     取得了将cookie数据字符串转为字典
            # 为取得则提前响应
            # 遍历cokie大字典将内部的每一个selected修改为true或false
            # 将字典转回字符串
            # 设置cookie
            # 响应

            cart_str = request.COOKIES.get('carts')
            if cart_str:
                cart_dict = pickle.loads(base64.b64decode(cart_str.encode()))
            else:
                return http.HttpResponseForbidden('cookie没有获取到')


            for sku_id in cart_dict:
                cart_dict[sku_id]['selected'] = selected
            cart_str = base64.b64encode(pickle.dumps(cart_dict)).decode()

            response = http.JsonResponse({'code':RETCODE.OK,'errmsg':'OK'})
            response.set_cookie('carts',cart_str)
            return response

class CartsSimpleView(View):
    def get(self,request):
        user = request.user
        if user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            redis_carts = redis_conn.hgetall('cart_%s' % user.id)
            selected_ids = redis_conn.smembers('selected_%s' % user.id)
            cart_dict = {}  # 用来包装redis购物车的所有数据
            for sku_id_bytes in redis_carts:
                cart_dict[int(sku_id_bytes)] = {
                    'count': int(redis_carts[sku_id_bytes]),
                    'selected': sku_id_bytes in selected_ids
                }
        else:
            cart_str = request.COOKIES.get('carts')
            if cart_str:
                cart_dict = pickle.loads(base64.b64encode(cart_str.encode()))
            else:
                return render(request,'cart.html')
        sku_qs = SKU.objects.filter(id__in=cart_dict.keys())
        sku_list = []
        for sku_model in sku_qs:
            count = cart_dict[sku_model.id]['count']
            sku_list.append({
                'id' :sku_model.id,
                'name' : sku_model.name,
                'default_image_url': sku_model.default_image.url,
                'count':count
            })
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'cart_skus': sku_list})




















